﻿/**
  \file memory_image.c

  \author G. Icking-Konert

  \brief implementation of memory image and functions to manipulate it

  implementation of memory image and functions to manipulate it
*/

/**********************
 INCLUDES
**********************/
#include <time.h>
#include <string.h>
#include <math.h>
#include <inttypes.h>
#include "memory_image.h"


/**********************
 LOCAL MACROS
**********************/
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))


/**********************
 GLOBAL FUNCTIONS
**********************/

void MemoryImage_init(MemoryImage_s* image) {
    
    // initialize struct variables
    image->firstMemoryEntries = NULL;
    image->lastMemoryEntries = NULL;
    image->numEntries = 0;

} // MemoryImage_init()


void MemoryImage_free(MemoryImage_s* image) {

    MemoryEntry_s* p_1,*p_2;

    p_1 = image->lastMemoryEntries;
    while(p_1 != NULL)
    {
        p_2 = p_1;
        p_1 = p_1->prev;
        free(p_2->data);  // release memory buffer 
        free(p_2);        // release memory entry
        if(p_1 != NULL)
        {p_1->next = NULL;}
        image->numEntries--;
        image->lastMemoryEntries = p_1;   
    }
    // reset struct variables
    image->firstMemoryEntries = NULL;
    image->lastMemoryEntries = NULL;
    image->numEntries = 0;

} // MemoryImage_free()


bool MemoryImage_addData(MemoryImage_s* image, const MEMIMAGE_ADDR_T address, const uint8_t data) {

    // if first add data
    if((image->firstMemoryEntries == NULL )&&( image->lastMemoryEntries == NULL))
    {
        image->lastMemoryEntries = (MemoryEntry_s*)malloc(sizeof(MemoryEntry_s));
        image->lastMemoryEntries->data = malloc(MEMIMAGE_BUFFER_MAX);
        image->lastMemoryEntries->capacityRsrv = MEMIMAGE_BUFFER_MAX;
        image->lastMemoryEntries->capacityUsed = 0;
        image->lastMemoryEntries->alreadyRead = 0;
        image->lastMemoryEntries->addrStart = address;
        image->lastMemoryEntries->next = NULL;
        image->lastMemoryEntries->prev = NULL;
        image->firstMemoryEntries = image->lastMemoryEntries;
        image->numEntries = 1;
    }
    

    if(image->lastMemoryEntries->capacityRsrv != 0)
    {
        // 在同一个段落
        if((address-image->lastMemoryEntries->capacityUsed == image->lastMemoryEntries->addrStart))
        {
            image->lastMemoryEntries->data[image->lastMemoryEntries->capacityUsed++] = data;
            image->lastMemoryEntries->capacityRsrv--;
        }
        else    //不在同一段落
        {
            image->lastMemoryEntries->data = realloc(image->lastMemoryEntries->data, image->lastMemoryEntries->capacityUsed);
            image->lastMemoryEntries->capacityRsrv = image->lastMemoryEntries->capacityUsed - image->lastMemoryEntries->capacityUsed;
            image->lastMemoryEntries->next = (MemoryEntry_s*)malloc(sizeof(MemoryEntry_s));
            image->lastMemoryEntries->next->prev = image->lastMemoryEntries;
            image->lastMemoryEntries = image->lastMemoryEntries->next;
            image->numEntries++;
            image->lastMemoryEntries->data = malloc(MEMIMAGE_BUFFER_MAX);
            image->lastMemoryEntries->capacityRsrv = MEMIMAGE_BUFFER_MAX;
            image->lastMemoryEntries->capacityUsed = 0;
            image->lastMemoryEntries->alreadyRead = 0;
            image->lastMemoryEntries->addrStart = address;
            image->lastMemoryEntries->next = NULL;
            MemoryImage_addData(image,address,data);
        }
    }
    else    //超出缓冲区限制
    {
        return false;
    }

    // return success
    return true;

} // MemoryImage_addData()

// end of file
